package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"net"
)

type msg struct {
	Sender   string
	Receiver string
	Content  string
}

func process(conn net.Conn) {
	reader := bufio.NewReader(conn)
	var buf [128]byte
	n, err := reader.Read(buf[:]) //  1 读取数据

	if err != nil {
		//fmt.Println("read from client failed, err:", err)
		return
	}
	//把用户加入到map
	userName := string(buf[:n])
	userOnline[userName] = conn
	for s, n2 := range userOnline {
		if s != userName {
			n2.Write([]byte(userName + "上线了!"))
		}
	}
	receiveAndSendMessage(conn, userName)
	return
}

func receiveAndSendMessage(conn net.Conn, name string) {

	for {
		date := ""
		reader := bufio.NewReader(conn)
		for {
			var buf [1024]byte
			n, err := reader.Read(buf[:]) // 读取数据
			if err != nil {
				//用户退出后删除map中的该用户
				defer delete(userOnline, name)
				//给除了该用户的用户发送消息：告知下线通知
				for s, n2 := range userOnline {
					if s != name {
						n2.Write([]byte(name + "下线了!"))
					}
				}
				fmt.Println("read from client failed, err:", err)
				conn.Close()
				return
			}
			recvStr := string(buf[:n])
			//fmt.Println(recvStr)
			date += recvStr
			break
		}
		mess := msg{}
		err := json.Unmarshal([]byte(date), &mess)
		if err != nil {
			fmt.Println("json unmarshal failed!")
			return
		}

		receiver := mess.Receiver
		sender := mess.Sender
		content := mess.Content
		//接收到的是下线通知
		if receiver == "drop" && content == "drop" {
			//用户退出后删除map中的该用户
			defer delete(userOnline, name)
			//给除了该用户的用户发送消息：告知下线通知
			for s, n2 := range userOnline {
				if s != name {
					n2.Write([]byte(name + "下线了!"))
				}
			}
			conn.Close()
			return
		}
		if receiver == "1" {
			//发送给所有人
			for s, n2 := range userOnline {
				if s != sender {
					temp := content
					content = sender + ":" + content
					//fmt.Println(content)
					_, err := n2.Write([]byte(content))
					if err != nil {
						fmt.Printf("Sever send err:%v", err)
					}
					content = temp
				}
			}
			conn.Write([]byte("发送成功"))
		} else {
			//发送给指定的人
			if v, ok := userOnline[receiver]; ok {
				content = sender + ":" + content
				fmt.Println(content)
				_, err := v.Write([]byte(content))
				if err != nil {
					fmt.Printf("Sever send err:%v", err)
				}
				conn.Write([]byte("发送成功"))

			} else {
				conn.Write([]byte("发送失败," + receiver + "用户不在线，当前在线用户"))
				for i, _ := range userOnline {
					conn.Write([]byte(i + "\n"))
				}
			}

		}

	}
}

var userOnline = make(map[string]net.Conn, 10)

func main() {
	listen, err := net.Listen("tcp", "127.0.0.1:20000")
	if err != nil {
		fmt.Println("listen failed, err:", err)
		return
	}
	for {
		conn, err := listen.Accept() // 建立连接
		if err != nil {
			fmt.Println("accept failed, err:", err)
			continue
		}
		go process(conn) // 启动一个goroutine处理连接
	}
}
